"""
Code based on HashSourceCodes found at opensubtitle.org API Documentation
http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes
"""

import struct
import os

class HashFile(object):
    
    __LONG_LONG_FORMAT = "q"
    __FILE_OPEN_MODE = "rb"
    __SIX_FOUR_BYTE_CODE =  0xFFFFFFFFFFFFFFFF
    __MIN_FILE_SIZE = 65536
    
    def __init__(self, file_name):
        self.file = file_name
        
    def hash(self):
        f = None
        try:
            bytesize = struct.calcsize(self.__LONG_LONG_FORMAT) 
            f = open(self.file, self.__FILE_OPEN_MODE) 
            filesize = self.size()
            hash = filesize 
            if filesize < self.__MIN_FILE_SIZE * 2: 
                return "SizeError" 
            
            for x in range(self.__MIN_FILE_SIZE/bytesize): 
                buffer = f.read(bytesize) 
                (l_value,)= struct.unpack(self.__LONG_LONG_FORMAT, buffer)  
                hash += l_value 
                hash = hash & self.__SIX_FOUR_BYTE_CODE #to remain as 64bit number  
    
            f.seek(max(0,filesize-self.__MIN_FILE_SIZE),0) 
            for x in range(self.__MIN_FILE_SIZE/bytesize): 
                buffer = f.read(bytesize) 
                (l_value,)= struct.unpack(self.__LONG_LONG_FORMAT, buffer)  
                hash += l_value 
                hash = hash & self.__SIX_FOUR_BYTE_CODE
                 
            returnedhash =  "%016x" % hash 
            return returnedhash 
    
        except IOError: 
            return "IOError"
               
        finally:
            if f is not None:
                f.close

    def size(self):
        return os.path.getsize(self.file)